Quartz使用Trigger
,Job
和JobDetail
来实现各种调度任务。Quartz的基础概念可以查看http://quartz-scheduler.org。为了方便,Spring提供了在Spring基础应用下简单使用Quartz的数个类。
Quartz JobDetail
对象包含了执行一个工作任务的所有必要信息。Spring提供JobDetailFactoryBean
以XML格式配置Bean样式的属性。让我们来看一个例子:
<bean name="exampleJob" class="org.springframework.sheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="example.ExampleJob" />
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="5" />
</map>
</property>
</bean>
工作任务细节配置包含了执行的所有需要的信息(ExampleJob
)。timeout是在工作任务数据以键值形式被指定。工作任务数据键值可以通过JobExecutionContext
工作执行上下文获取(在执行期间传递),但是JobDetail
也是通过工作实例被数据映射的属性来得到它的属性值。所以在这个例子中,如果ExampleJob
包含了一个名称为timeout
的bean属性,JobDetail
将会自动获取到:
package example;
public class ExampleJob extends QuarztJobBean {
private int timeout;
/**
* Setter called after the ExampleJob is instantiated
* with the value from the JobDetailFactoryBean(5)
*/
public void setTimeout(int timeout) {
this.timeout = timeout;
}
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
// do the actual work
}
}
通过工作数据键值配置的所有附件属性也都是可用的。
使用
name
和group
属性,可以分别改变工作的名称和组。工作的名称默认是匹配JobDetailFactoryBean
的名称(在上面的例子中,就是exampleJob
)
经常需要调用特定对象的方法。使用MethodInvokingJobDetailFactoryBean
可以实现这一点:
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="exampleBusinessObject" />
<property name="targetMethod" value="doIt" />
</bean>
上面的例子将会调用exampleBusinessObject
对象的doIt
方法:
public class ExampleBusinessObject { // properties and collaborators public void doIt() { // do the actual work } }
<bean id="exampleBusinessObject" class="examples.ExampleBusinessObject" />
使用MethodInvokingJobDetailFactoryBean
,不需要去创建一个仅仅实现调用方法的主工作任务,只需创建真正业务逻辑对象和关注对象实现的细节。
Quartz工作任务默认是无状态的,导致的结果工作任务之间会相互干扰。如果给同一个JobDetail
指定两个触发器,可能会出现在第一个任务完成之前,第二个任务就要开始了。如果JobDetail
类实现了Stateful
接口,这种情况就不会发生。在第一个任务完成之前第二个任务将不会开始。为了使任务通过MethodInvokingJobDetailFactoryBean
不并发,设置concurrent
标志为false
。
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="exampleBusinessObject" />
<property name="targetMethod" value="doIt" />
<property name="concurrent" value="false" />
</bean>
默认的工作任务是在并发形式下执行的
我们已经创建了工作任务和任务的实现。也有方便的bean来调用指定的对象方法。我们仍然需要这些工作任务自己进行调度。使用触发器和SchedulerFactoryBean
来完成。Quartz实现了几个触发器,Spring提供两个方便的Quartz FactoryBean
实现:CronTriggerFactoryBean
和SimpleTriggerFactoryBean
。
触发器是需要被安排调用的。Spring提供SchedulerFactoryBean使触发器做可以设置的属性暴露出来。SchedulerFactoryBean
使用触发器来安排调用工作任务。
下面是两个例子:
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<!-- see the example of method invoking job above -->
<property name="jobDetail ref="jobDetail" />
<!-- 10 seconds -->
<property name="startDelay" value="10000" />
<!-- repeat every 50 seconds -->
<property name="repeatInterval" value="50000" />
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="exampleJob" />
<!-- run every morning at 6 AM -->
<property name="cronExpression" value="0 0 6 * * ?" />
</bean>
现在我们已经设置了两个触发器,一个每隔50秒延迟10秒启动一个次和一个每天在上6点执行。最后我们需要设置SchedulerFactoryBean
:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
<ref bean="simpleTrigger" />
</list>
</property>
</bean>
SchedulerFactoryBean
更多的可设置属性,例如工作任务实现使用的calendars,Quartz自定义的属性等等。查看SchedulerFactoryBean
的javadocs了解更多信息。